"""
Fibonacci数列的所有问题
生成器：普通函数return改成yield；生成器字面量语法
迭代器：
    ~ 写一个有__next__和__iter__魔术方法的类，那么这个类的对象就是一个迭代器对象
    ~ 通过内置函数iter()创建迭代器对象
迭代器可以通过next()函数和for-in循环取值
"""


class Countdown:
    """倒计数迭代器"""

    def __init__(self, num, step=1):
        self.num = num
        self.step = step
    
    def __iter__(self):
        return self
    
    def __next__(self):
        current = self.num
        if self.num < 0:
            raise StopIteration()
        self.num -= self.step
        return current


# for value in Countdown(10):
#     print(value)


def fib1(num):
    a, b = 0, 1
    for _ in range(num):
        a, b = b, a + b
    return a


def fib2(num, temp={}):
    if num == 0:
        return 0
    elif num == 1:
        return 1
    if num not in temp:
        temp[num] = fib2(num - 1) + fib2(num - 2)
    return temp[num]


def fib3(num):
    a, b = 0, 1
    for _ in range(num):
        yield a
        a, b = b, a + b


class Fib4:

    def __init__(self, num):
        self.start, self.end = 0, num
        self.a, self.b = 0, 1
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.start < self.end:
            current = self.a
            self.a, self.b = self.b, self.a + self.b
            self.start += 1
            return current
        raise StopIteration()


for value in Fib4(20):
    print(value)

# 生成器的字面量语法
# gen = (num for num in range(10, -1, -1))
# print(gen)
# for value in gen:
#     print(value)

# for num in range(121):
#     print(fib1(num))
# result = fib3(20)
# print(result)
# print(next(result))
# print(next(result))
# for value in result:
#     print(value)
